using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using 凌依.工具库;
using 凌依.工具库.U2D地图;
using 凌依.工具库.随机工具;
using System.Linq;
using Newtonsoft.Json;
public class 地面生成控制器 : 单例_基础可挂载管理器<地面生成控制器>
{
    //地图生成包括 
    /*
     
    生态环境
    山体
    矿物
    树木
    植物
    动物

    建筑
        商店
        住宅
        街道
        军事基地
     */

    public Tilemap 底层_地面;
    Tile 地面瓦片;

    public SpriteRenderer 地形图;
    public List<string> 生成信息 = new List<string>();

    public Sprite 预览图;

    void Start()
    {
        生成属性 = 地图参数.获取实例.参数信息;
        Debug.Log("获取完成");
    }
    
    private void OnValidate()
    {
        //生成墙壁();
    }

    [ContextMenu("生成贴图")]
    public void 生成地图()
    {
        StartCoroutine(生成墙壁());
    }
    public 地图参数包裹 生成属性;
    public IEnumerator 生成墙壁()
    {

        long 开始时间_总计 = 时间.时间戳_毫秒级();
        float[,] vs = new float[0, 0];
        float[,] vs2 = new float[0, 0];
        float[,] 生态群落 = new float[0, 0];
        float[,] 矿物 = new float[0, 0];
        float[,] 树木 = new float[0, 0];
        float[,] 森林地表矿 = new float[0, 0];

        生成信息.Add("多线程生成噪声中");

        后台管理.获取实例.添加后台委托(() => { 树木 = 柏林噪声.柏林噪声叠加(规格, 生成属性.树木生成); },()=> 生成信息.Add("森林群落生成完成"));
        后台管理.获取实例.添加后台委托(() => { vs2 = 柏林噪声.柏林噪声叠加(规格, 生成属性.山地群落); }, () => 生成信息.Add("岩石群落生成完成"));
        后台管理.获取实例.添加后台委托(() => { 生态群落 = 柏林噪声.柏林噪声叠加(规格, 生成属性.生态群落参数); }, () => 生成信息.Add("随机群落生成完成"));
        后台管理.获取实例.添加后台委托(() => { 矿物 = 柏林噪声.柏林噪声叠加(规格, 生成属性.矿物生成); }, () => 生成信息.Add("矿物群落生成完成"));
        后台管理.获取实例.添加后台委托(() => { vs = 柏林噪声.柏林噪声叠加(规格, 生成属性.山体参数); }, () => 生成信息.Add("地表岩石群落生成完成"));
        后台管理.获取实例.添加后台委托(() => { 森林地表矿 = 柏林噪声.柏林噪声叠加(规格, 生成属性.森林地表矿参数); }, () => 生成信息.Add("森林矿物群落生成完成"));


        while (true)
        {
            if (vs.Length != 0 && vs2.Length != 0 && 生态群落.Length != 0 && 矿物.Length != 0 && 树木.Length != 0 && 森林地表矿.Length!=0)
                break;
            yield return 0;
        }

        生成信息.Add("噪声生成完成");

        Dictionary<Vector2Int, bool> 群落坐标 = new Dictionary<Vector2Int, bool>();
        Dictionary<Vector2Int, bool> 矿物坐标 = new Dictionary<Vector2Int, bool>();
        List<List<Vector2Int>> 特殊群落分类 = new List<List<Vector2Int>>();
        List<List<Vector2Int>> 矿物坐标分类 = new List<List<Vector2Int>>();
        //100*100 为一个区块 显示玩家周围 9个区块 默认


        //地形图
        Texture2D 贴图 = Texture2D_工具.初始化图片(Color.black, 规格, 规格);
        贴图.filterMode = FilterMode.Point;

        生成属性_集合 平原 = new 生成属性_集合();
        生成属性_集合 森林 = new 生成属性_集合();
        生成属性_集合 森林矿物_聚集 = new 生成属性_集合();
        生成属性_集合 森林矿物 = new 生成属性_集合();
        生成属性_集合 岩石地形 = new 生成属性_集合();

        生成信息.Add("生成参数读取中");

        foreach (var item in 生成属性.生态道具生成集合)
        {
            switch (item.name)
            {
                case "平原":
                    平原 = item;
                    break;
                case "森林":
                    森林 = item;
                    break;
                case "森林矿物_聚集":
                    森林矿物_聚集 = item;
                    break;
                case "森林矿物":
                    森林矿物 = item;
                    break;
                case "岩石地形":
                    岩石地形 = item;
                    break;
            }
        }

        生成信息.Add("生成参数读取完成");
        生成信息.Add("生成地形中 0%");
        int 格子数量 = 规格 * 规格;
        int 当前格子数 = 0;
        int 总数 = 0;

        for (int x = 0; x < 规格; x++)
        {
            for (int y = 0; y < 规格; y++)
            {
                Vector2Int vector2Pos = new Vector2Int(x, y);
                void 添加数据(string name, 图层 图层)
                {
                    地图数据管理器.获取实例.添加瓦片_模板(vector2Pos, name);
                    //瓦片管理器.获取实例.设置瓦片(vector2Pos, 地图数据管理器.获取实例.读取瓦片(vector2Pos, 图层));
                }

                当前格子数++;
                if (当前格子数 >= 40000)
                {
                    总数 += 当前格子数;
                    当前格子数 = 0;
                    生成信息.Add($"生成地形中{ (总数 / (float)格子数量*100).ToString("0.0")}%");
                    yield return 0;
                }

                if (vs2[x, y] >= 生成属性.山地地形截取高度)//岩石地面
                {
                    添加数据("岩石地面", 图层.底层);
                    if (vs[x, y] >= 生成属性.山体截取高度 && vs2[x, y] >= 生成属性.山地地形截取高度 && 矿物[x, y] >= 生成属性.矿物高度截取)//岩石内矿物
                    {
                        矿物坐标.Add(vector2Pos, true);
                    }
                    else if (vs2[x, y] >= 生成属性.山地地形截取高度 && 矿物[x, y] >= 生成属性.矿物高度截取 + 0.13f)//裸漏矿物
                    {
                        矿物坐标.Add(vector2Pos, true);
                    }
                    else if (vs[x, y] >= 生成属性.山体截取高度 && vs2[x, y] >= 生成属性.山地地形截取高度)//岩石
                    {
                        添加数据("阴影", 图层.上层);
                        添加数据("岩石", 图层.中层);
                    }
                    else
                    {
                        string 生成 = 随机生成(岩石地形);
                        if (生成 != "空")
                            添加数据(生成, 图层.中层);
                    }
                }
                else if (生态群落[x, y] >= 生成属性.生态群落截取高低)//生态群落
                {
                    //随机 沙漠 雪地

                    //添加数据("沙漠", 图层.底层);
                    群落坐标.Add(vector2Pos, true);
                }
                else if (生态群落[x, y] <= 1 - 生成属性.大水湖高点)//大水湖 禁止生成城镇
                {
                    添加数据("深水", 图层.底层);
                }
                else if (vs[x, y] > 生成属性.小水湖高点 && vs2[x, y] <= 生成属性.山地地形截取高度)//小水湖 禁止生成城镇
                {
                    添加数据("浅水", 图层.底层);
                }
                else if (树木[x, y] >= 生成属性.森林截取高度 && vs2[x, y] <= 生成属性.山地地形截取高度)//森林
                {
                    添加数据("森林", 图层.底层);
                    if (森林地表矿[x, y] >= 生成属性.森林地表矿高点)//森林地表矿
                    {
                        //矿物 岩石或矿物
                        string 生成 = 随机生成(森林矿物_聚集);
                        if(生成!="空")
                            添加数据(生成, 图层.中层);
                    }
                    else
                    {
                        //树木
                        string 生成 = 随机生成(森林);
                        if(生成!="空")
                            实例化植物控制器.获取实例.设置数据(生成, vector2Pos);

                        string 生成1 = 随机生成(森林矿物);
                        if (生成1 != "空")
                            添加数据(生成1, 图层.中层);
                    }
                }
                else
                {
                    添加数据("草地", 图层.底层);

                    string 生成 = 随机生成(平原);
                    if (生成 != "空")
                        实例化植物控制器.获取实例.设置数据(生成, vector2Pos);
                }

                #region 画图
                if (vs[x, y] >= 生成属性.山体截取高度 && vs2[x, y] >= 生成属性.山地地形截取高度 && 矿物[x, y] >= 生成属性.矿物高度截取)//22222222222222222222222222
                {
                    贴图.SetPixel(x, y, "#ff0000".ToColor());//山地墙体矿物
                }
                else if (vs2[x, y] >= 生成属性.山地地形截取高度 && 矿物[x, y] >= 生成属性.矿物高度截取 + 0.13f)//333333333333333333333333333333333333333333
                {
                    贴图.SetPixel(x, y, "#ff00ff".ToColor());//山地裸漏矿物
                }
                else if (vs[x, y] >= 生成属性.山体截取高度 && vs2[x, y] >= 生成属性.山地地形截取高度)
                {
                    贴图.SetPixel(x, y, "#AB8C68".ToColor());//山地墙体
                }
                else if (vs2[x, y] >= 生成属性.山地地形截取高度)//111111111111111111111111111111
                {
                    贴图.SetPixel(x, y, "#666666".ToColor());//山地地形
                }

                else if (生态群落[x, y] >= 生成属性.生态群落截取高低)//生态群落
                {
                    贴图.SetPixel(x, y, "#559AC3".ToColor());
                    //群落坐标.Add(vector2Pos, true);
                }
                else if (生态群落[x, y] <= 1 - 生成属性.大水湖高点)
                {
                    贴图.SetPixel(x, y, "#4396A2".ToColor());//大水湖 禁止生成城镇
                }
                else if (vs[x, y] > 生成属性.小水湖高点 && vs2[x, y] <= 生成属性.山地地形截取高度)
                {
                    贴图.SetPixel(x, y, "#4396A2".ToColor());//小水湖 禁止生成城镇
                }
                else if (森林地表矿[x, y] >= 生成属性.森林地表矿高点)
                {
                    贴图.SetPixel(x, y, "#464646".ToColor());//森林地表矿
                }
                else if (树木[x, y] >= 生成属性.森林截取高度 && vs2[x, y] <= 生成属性.山地地形截取高度)//森林
                {
                    贴图.SetPixel(x, y, "#275A29".ToColor());
                }
                else
                {
                    贴图.SetPixel(x, y, "#5D8C3E".ToColor());//草地
                }
                #endregion
            }
        }

        生成信息.Add("地形生成完成");

        string 随机生成_自定义(生成属性_集合 数据,int 增加稀有度)
        {
            int 选中 = Random.Range(0, 数据.上限) + 增加稀有度;
            选中 = Mathf.Clamp(选中, 0, 数据.上限);
            int 累计 = 0;

            for (int i = 0; i < 数据.集合.Count; i++)
            {
                int min = i == 0 ? 0 : 数据.集合[i-1].随机几率;
                int max = 累计+数据.集合[i].随机几率;
                if(选中<=max && 选中>= min)
                    return 数据.集合[i].名称;
                累计 += 数据.集合[i].随机几率;
            }
           
            return "空";
        }
        string 随机生成(生成属性_集合 数据)
        {
            return 随机生成_自定义(数据, 0);
        }

        生成信息.Add("分拣相邻生态系统");

        void 相邻分类(Dictionary<Vector2Int, bool> 坐标, List<List<Vector2Int>> 分类)
        {
            while (坐标.Count != 0)
            {
                Vector2Int 起始 = 坐标.FirstOrDefault().Key;

                List<Vector2Int> 激活表 = new List<Vector2Int>();
                List<Vector2Int> 选中群落坐标 = new List<Vector2Int>();

                坐标.Remove(起始);
                选中群落坐标.Add(起始);

                foreach (var item in 起始.Get4pos())
                {
                    if (坐标.ContainsKey(item))
                    {
                        坐标.Remove(item);
                        激活表.Add(item);
                    }
                }

                while (激活表.Count != 0)
                {
                    起始 = 激活表[0];
                    激活表.RemoveAt(0);
                    选中群落坐标.Add(起始);
                    foreach (var item in 起始.Get4pos())
                    {
                        if (坐标.ContainsKey(item))
                        {
                            坐标.Remove(item);
                            激活表.Add(item);
                        }
                    }
                }

                分类.Add(选中群落坐标);
            }
        }


        long 开始时间 = 时间.时间戳_毫秒级();
        相邻分类(群落坐标, 特殊群落分类);
        Debug.Log("选中算法:" + (时间.时间戳_毫秒级() - 开始时间));
        生成信息.Add("选中特殊生态群落完成");
        yield return 0;



        long 矿物开始时间 = 时间.时间戳_毫秒级();
        相邻分类(矿物坐标, 矿物坐标分类);
        Debug.Log("矿物算法:" + (时间.时间戳_毫秒级() - 矿物开始时间));
        生成信息.Add("选中矿物完成");
        yield return 0;

        //矿物生成
        long 矿物_开始时间 = 时间.时间戳_毫秒级();
        int 矿物_参数上限 = 生成属性.矿物生成参数.上限;
       

        foreach (var item in 矿物坐标分类)
        {
            if (item.Count <= 5)
            {
                //当矿物相连接的数量小于4,转为岩石
                foreach (var pos in item)
                {
                    地图数据管理器.获取实例.添加瓦片_模板(pos, "岩石");
                    地图数据管理器.获取实例.添加瓦片_模板(pos, "阴影");
                }
            }
            else
            {
                int 当前选择 = 随机.随机范围(矿物_参数上限);
                int 累计 = 0;
                for (int i = 0; i < 生成属性.矿物生成参数.集合.Count; i++)
                {
                    int min = i == 0 ? 0 : 生成属性.矿物生成参数.集合[i - 1].随机几率;
                    int max = 累计 + 生成属性.矿物生成参数.集合[i].随机几率;

                    if (当前选择>= min && 当前选择<=max)
                    {
                        foreach (var pos in item)
                        {
                            地图数据管理器.获取实例.添加瓦片_模板(pos, 生成属性.矿物生成参数.集合[i].名称);
                            地图数据管理器.获取实例.添加瓦片_模板(pos, "阴影");
                        }
                        break;
                    }
                    累计 += 生成属性.矿物生成参数.集合[i].随机几率;
                }
            }
        }
        Debug.Log("矿物详细算法:" + (时间.时间戳_毫秒级() - 矿物_开始时间));
        生成信息.Add("细化矿物完成");
        yield return 0;



        long 群落_开始时间 = 时间.时间戳_毫秒级();
        特殊群落分类 = 特殊群落分类.OrderByDescending((t) => t.Count).ToList();

        for (int i = 0; i < 特殊群落分类.Count; i++)
        {
            string 群落名 = 随机生成_自定义(生成属性.生态地形生成参数, i);

            Color 预览图底色 = Random.ColorHSV();
            switch (群落名)
            {
                case "沙漠":
                    预览图底色 = "#FFCD6E".ToColor();
                    break;
                case "雪地":
                    预览图底色 = "#EBFAFF".ToColor();
                    break;
                default:
                    break;
            }

            foreach (var item in 特殊群落分类[i])
            {
                地图数据管理器.获取实例.添加瓦片_模板(item, 群落名);
                贴图.SetPixel(item.x, item.y, 预览图底色);
            }
        }
        生成信息.Add("生成完成,正在保存地图");

        Debug.Log("群落算法:" + (时间.时间戳_毫秒级() - 群落_开始时间));
        #region 画图

        贴图.Apply();
        预览图 = Sprite.Create(贴图, new Rect(0, 0, 规格, 规格), Vector2.zero);
        #endregion

        Debug.Log(时间.时间戳_毫秒级() - 开始时间_总计);
    }


    public int 规格;
    
}
